// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 .
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : cpu_ready_drv.sv
// Author        : 
// Created On    : 2022-08-25 17:36
// Last Modified : 
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

`ifndef __CPU_READY_DRV_SV__
`define __CPU_READY_DRV_SV__

class cpu_ready_drv extends uvm_component;
	virtual cpu_interface vif;
	
	`uvm_component_utils(cpu_ready_drv)
	
	extern function new(string name = "cpu_ready_drv", uvm_component parent=null);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual task main_phase(uvm_phase phase);
endclass: cpu_ready_drv

function cpu_ready_drv::new(string name = "cpu_ready_drv", uvm_component parent=null);
	super.new(name, parent);
endfunction: new

function void cpu_ready_drv::build_phase(uvm_phase phase);
	super.build_phase(phase);
	`uvm_info("cpu_ready_drv", "build_phase is called", UVM_LOW);
	if(!uvm_config_db #(virtual cpu_interface)::get(this, "", "vif", vif))begin
		`uvm_fatal("cpu_ready_drv", "virtual interface get fatal");
	end
endfunction: build_phase

task cpu_ready_drv::main_phase(uvm_phase phase);
    int cpu_ready_phase = 0;
    
    @this.vif.ready_drv;
    this.vif.ready_drv.CPU_RDY_N <= 1'b0;
    this.vif.ready_drv.CPU_RDATA <= 'dx;

    while(!this.vif.rst_n) @this.vif.ready_drv;

	fork 
		while(1)begin
            @this.vif.ready_drv;
            if(cpu_ready_phase === 0 && this.vif.ready_drv.CPU_CS_N === 1'b0)begin
                repeat($urandom_range(1)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b1;
                cpu_ready_phase = 1;
                continue;
            end
            else if(cpu_ready_phase == 1 && this.vif.ready_drv.CPU_RD_N === 1'b0)begin
                repeat($urandom_range(8,10)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b0;
                cpu_ready_phase = 2;
                continue;
            end
            else if(cpu_ready_phase == 1 && this.vif.ready_drv.CPU_WE_N === 1'b0)begin
                repeat($urandom_range(8,10)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b0;
                cpu_ready_phase = 2;
                continue;
            end
            else if(cpu_ready_phase == 2 && this.vif.ready_drv.CPU_RD_N === 1'b1)begin
                repeat($urandom_range(1,8)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b1;
                cpu_ready_phase = 3;
                continue;
            end
            else if(cpu_ready_phase == 2 && this.vif.ready_drv.CPU_WE_N === 1'b1)begin
                repeat($urandom_range(1,8)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b1;
                cpu_ready_phase = 3;
                continue;
            end
            else if(cpu_ready_phase === 3 && this.vif.ready_drv.CPU_CS_N === 1'b1)begin
                repeat($urandom_range(3,12)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDY_N <= 1'b0;
                cpu_ready_phase = 0;
            end
        end
        while(1)begin
            @this.vif.ready_drv;
            if(this.vif.ready_drv.CPU_RD_N === 1'b0 && this.vif.ready_drv.CPU_RD_N_ff === 1'b1)begin
                repeat($urandom_range(2,6)) @this.vif.ready_drv;
                this.vif.ready_drv.CPU_RDATA <= $urandom;
            end
        end
	join_none
endtask: main_phase

`endif
